package pl.gigiel.behaviour.steermanager;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import pl.gigiel.behaviour.IBoid;
import pl.gigiel.behaviour.ISteer;
import pl.gigiel.behaviour.ISteerManager;
import pl.gigiel.behaviour.exception.BehaviourException;

import com.jme.math.Vector3f;

public class SimpleSteerManager implements ISteerManager {
	private Map<Float, List<SteerItem>> steersByPriority;

	public SimpleSteerManager() {
		steersByPriority = new TreeMap<Float, List<SteerItem>>();
	}

	@Override
	public void add(ISteer steer, float priority, float weight, float strength) throws BehaviourException {
		List<SteerItem> list = steersByPriority.get(priority);
		if (list == null) {
			list = new ArrayList<SteerItem>();
			steersByPriority.put(priority, list);
		}
		list.add(new SteerItem(steer, priority, weight, strength));
	}

	@Override
	public void init() throws BehaviourException {
	}

	@Override
	public void reset() throws BehaviourException {
		steersByPriority.clear();
	}

	@Override
	public Vector3f resultant(IBoid boid, float elapsed) throws BehaviourException {
		Vector3f resultant = null;
		Vector3f part = null;
		// ascending order
		for (Float priority : steersByPriority.keySet()) {
			for (SteerItem steerItem : steersByPriority.get(priority)) {
				part = steerItem.steer.force(boid, elapsed);
				if (part != null) {
					if (resultant == null) {
						resultant = new Vector3f();
					}
					resultant.addLocal(part.mult(steerItem.strength));
				}
			}
			if (resultant != null) {
				break;
			}
		}
		return resultant;
	}

	private class SteerItem {
		public ISteer steer;
		public float priority;
		public float weight;
		public float strength;

		public SteerItem(ISteer steer, float priority, float weight, float strength) {
			this.steer = steer;
			this.priority = priority;
			this.weight = weight;
			this.strength = strength;
		}
	}
}
